package sim.net.euclidean;

import java.awt.*;
import java.util.*;
import java.awt.geom.*;

import sim.core.*;
import sim.util.*;

public class RandomEucledianNetwork extends Network implements Displayable {

	private final WeakHashMap<EuclideanNode, Integer> nodes = new WeakHashMap<EuclideanNode, Integer>();

	synchronized public EndPoint newEndPoint(MessageHandler handler) {
		EuclideanNode res = new EuclideanNode(handler, getRandomPosition(130));
		nodes.put(res, 0);
		return res;
	}

	synchronized EndPoint replaceEndPoint(EndPoint old) {
		EuclideanNode res = new EuclideanNode(null, old.pos);
		nodes.put(res, 0);
		return res;
	}

	public void disposeEndPoint(EndPoint x) {
	}

	synchronized public void display(Graphics2D gu, Graphics2D gs) {
		super.display(gu, gs);

		for (Map.Entry<EuclideanNode, Integer> i : nodes.entrySet()) {
			EuclideanNode n = i.getKey();
			if (n != null)
				n.display(gu, gs);
		}
	}

	private XY getRandomPosition(double minDistance) {
		ArrayList<EuclideanNode> x = new ArrayList<EuclideanNode>(nodes
				.keySet());
		Searching: for (;;) {
			XY pos = new XY().scale(sim.gui.Panel.S);
			if (minDistance > 0)
				for (EuclideanNode i : x)
					if (i != null && pos.distance(i.pos) < minDistance)
						continue Searching;

			return pos;
		}
	}

	@Override
	public Set<EndPoint> endpoints() {
		Set<EndPoint> res = new HashSet<EndPoint>();
		for (Map.Entry<EuclideanNode, Integer> i : nodes.entrySet()) {
			EuclideanNode n = i.getKey();
			if (n != null)
				res.add(n);
		}
		return res;
	}

	class EuclideanNode extends EndPoint {

		EuclideanNode(MessageHandler handler, XY pos) {
			super(handler);
			this.pos = pos;
		}

		public double distance(EndPoint other) {
			return pos.distance(((EuclideanNode) other).pos) * 0.00001;
		}

		public void display(Graphics2D gu, Graphics2D gs) {
			final double S = 30;
			final double hS = S / 2;
			gs.setColor(color);
			gs.setStroke(new BasicStroke(2f));
			if (!online)
				gs.fill(new Ellipse2D.Double(pos.x - hS, pos.y - hS, S, S));
			else
				gs.draw(new Ellipse2D.Double(pos.x - hS, pos.y - hS, S, S));

			gs.setColor(Color.black);
			gs.drawString(handler.toString(), (float) pos.x - 10,
					(float) pos.y - 20);
		}

		public void dispose() {
			online = false;
		}

		public String toString() {
			return handler.toString();
		}

		@Override
		public EndPoint replace() {
			return replaceEndPoint(this);
		}
	}
}